﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using System.ServiceModel;
using FMPCore;
using FMPCore.Interfaces;
using Client.UserControls;
using System.ComponentModel;
using System.Net;

namespace Client
{
    /// <summary>
    /// Interaction logic for winMain.xaml
    /// </summary>
    [CallbackBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public partial class winMain : Window, IMessageCallback
    {
        private IMessage proxy;

        private const string m_IPADDRESS = "127.0.0.1";
        private const string m_PORT = "8731";

        private const int m_FILETRANSFERPORT = 5656;

        private string m_username = string.Empty;
        BackgroundWorker m_bwUpdateContactList;

        public winMain()
        {
            InitializeComponent();

            GetComputerIPAddress();

            // Set up contact list update BackgroundWorker
            m_bwUpdateContactList = new BackgroundWorker();
            m_bwUpdateContactList.DoWork += new DoWorkEventHandler(m_bwUpdateContactList_DoWork);
            m_bwUpdateContactList.WorkerSupportsCancellation = true;

            // Get command line args
            Dictionary<string, string> cmdArgs =
                Application.Current.Properties["CommandLineArgs"] as Dictionary<string, string>;

            if (cmdArgs == null)
            {
                m_cmdArgs = new Dictionary<string, string>();
            }
            else
            {
                m_cmdArgs = cmdArgs;
            }
        }

        private List<IPAddress> m_computerAddressList;

        private void GetComputerIPAddress()
        {
            m_computerAddressList = new List<IPAddress>();

            IPHostEntry host = Dns.GetHostEntry(Dns.GetHostName());
            foreach (IPAddress ip in host.AddressList)
            {
                if (ip.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork)
                {
                    m_computerAddressList.Add(ip);
                }
            }
        }

        private readonly Dictionary<string, string> m_cmdArgs;

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            proxy = DuplexChannelFactory<IMessage>.CreateChannel
            (
                new InstanceContext(this),
                new NetTcpBinding(SecurityMode.None),
                new EndpointAddress(string.Format("net.tcp://{0}:{1}/Server/Message", m_IPADDRESS, m_PORT))
            );

            winLogin login = new winLogin(proxy);
            login.Owner = this;

            string username = string.Empty;
            if (m_cmdArgs.TryGetValue("-u", out username))
            {
                m_username = username;
                login.Username = m_username;

                string password = string.Empty;
                if (m_cmdArgs.TryGetValue("-p", out password))
                {
                    login.Password = password;
                }
            }

            Nullable<bool> dialogResult = login.ShowDialog();
            //Nullable<bool> dialogResult = true;
            if (dialogResult != null && dialogResult != false)
            {
                // Login sucessful
                m_username = login.Username;

                // Start the contact updater
                bwContactListUpdateArgs bwCUArgs = new bwContactListUpdateArgs { CurrentUser = m_username, MsgProxy = proxy };
                m_bwUpdateContactList.RunWorkerAsync(bwCUArgs);

                // Set contact list
                //ucContactList.SetContacts = proxy.GetContactList(m_username);
            }
            else
            {
                // Login failed or canceled
                this.Close();
            }
        }

        private void miExit_Click(object sender, RoutedEventArgs e)
        {
            m_bwUpdateContactList.CancelAsync();
            this.Close();
        }

        #region IMessageCallback Members

        public void RecieveMessage(ChatMessage message)
        {
            TabItem tiUser = null;

            for (int i = 1; i < tabContent.Items.Count; i++)
            {
                if (tabContent.Items[i] is TabItem)
                {
                    TabItem ti = tabContent.Items[i] as TabItem;
                    if (ti.Header.ToString() == message.From)
                    {
                        tiUser = ti;
                        ti.Focus();
                        break;
                    }
                }
            }

            // Create chat tab
            if (tiUser == null)
            {
                ucChat chat = new ucChat(message.From);
                chat.SendMessage += new ucChat.SendMessageEventHandler(chat_SendMessage);

                TabItem ti = new TabItem();
                ti.Header = message.From;
                ti.Content = chat;
                tiUser = ti;

                tabContent.Items.Add(ti);
                ti.Focus();
            }

            if (tiUser.Content is ucChat)
            {
                ucChat chat = tiUser.Content as ucChat;
                chat.AppendReceivedMessage(message);
                tiUser.Focus();
            }
        }

        void chat_SendMessage(object sender, ChatMessage e)
        {
            e.From = m_username;
            proxy.SendMessage(e);
        }

        public FileTransferMessageArgsResponse RecieveFileTransferRequest(FileTransferMessageArgs msgFileTransferArgs)
        {
            if (MessageBox.Show(string.Format("{0} want to send file: {1}, size: {2}.",
                msgFileTransferArgs.From, msgFileTransferArgs.FileName, msgFileTransferArgs.FileLength),
                "File Transfer Request", MessageBoxButton.OKCancel, MessageBoxImage.Question)
                == MessageBoxResult.OK)
            {
                ucFileTrans.AddFileToReceive(msgFileTransferArgs);
                return new FileTransferMessageArgsResponse(true, m_computerAddressList);
            }
            else
            {
                return new FileTransferMessageArgsResponse(false, null);
            }
        }

        #endregion

        #region File Transfer Stuff

        private List<BackgroundWorker> m_listOfBackgroundWorkers = new List<BackgroundWorker>();

        void bwFileTransfer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            BackgroundWorker bw = sender as BackgroundWorker;
        }

        void bwFileTransfer_DoWork(object sender, DoWorkEventArgs e)
        {
            throw new NotImplementedException();
        }

        #endregion

        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
        {
            try
            {
                proxy.Logout(m_username);
            }
            catch (Exception ex)
            {
                // TODO: correct exception
            }
        }

        private void ucContactList_OpenChat(object sender, string username)
        {
            if (!string.IsNullOrEmpty(username))
            {
                ucChat chat = new ucChat(username);
                chat.SendMessage += new ucChat.SendMessageEventHandler(chat_SendMessage);

                bool flag = false;
                foreach (TabItem it in tabContent.Items)
                {
                    if (it.Header.ToString() == username)
                    {
                        it.Focus();
                        flag = true;
                    }
                }
                if (!flag)
                {
                    TabItem ti = new TabItem();
                    ti.Header = username;
                    ti.Content = chat;
                    tabContent.Items.Add(ti);
                    ti.Focus();
                    
                }
            }
        }

        #region Contact List

        #region  Add/Remove

        private void ucContactList_AddContact(object sender, string username)
        {
            winAddContact addUser = new winAddContact(proxy, m_username);
            Nullable<bool> dialogResult = addUser.ShowDialog();

            if (dialogResult == null && dialogResult == false)
            {
                MessageBox.Show("User was not added to your contact list.", "Notice", MessageBoxButton.OK, MessageBoxImage.Asterisk);
            }
            else
            {
                // User was added sucessfully, now get the updated contact list
                ucContactList.SetContacts = proxy.GetContactList(m_username);
            }
        }

        private void ucContactList_RemoveContact(object sender, string username)
        {
            if (proxy.RemoveContact(m_username, username))
            {
                // User was removed successfully, now get the updated contact list
                ucContactList.SetContacts = proxy.GetContactList(m_username);
            }
            else
            {
                MessageBox.Show(string.Format("Could not remove user: {0} from your contact list.", username),
                    "Failed to remove user", MessageBoxButton.OK, MessageBoxImage.Warning);
            }
        }

        #endregion

        #region File Transfer

        private void ucContactList_SendFileToUser(object sender, string username)
        {
            Microsoft.Win32.OpenFileDialog dlg = new Microsoft.Win32.OpenFileDialog();

            // Display OpenFileDialog by calling ShowDialog method
            Nullable<bool> result = dlg.ShowDialog();

            // Get the selected file name and display in a TextBox
            if (result == true)
            {
                // Open document
                string filename = dlg.FileName;
                System.IO.FileInfo fi = new System.IO.FileInfo(filename);


                // Send request to user
                FileTransferMessageArgs ftma = new FileTransferMessageArgs
                {
                    From = m_username,
                    To = username,
                    FileName = fi.Name,
                    FileLength = fi.Length,
                    FileHash = string.Empty
                };
                FileTransferMessageArgsResponse res = proxy.SendFileTransferRequestMessage(ftma);
                if (res.Accepted)
                {
                    ucFileTrans.AddFileToSend(dlg.FileName, res.IPAddresses);
                }
                else
                {
                    MessageBox.Show("User did not accept the file transfer request.");
                }
            }
        }

        #endregion

        #region BackgroundUpdate

        void m_bwUpdateContactList_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;
            bwContactListUpdateArgs args = e.Argument as bwContactListUpdateArgs;

            if (args != null)
            {
                while (!worker.CancellationPending)
                {
                    List<Contact> contacts = args.MsgProxy.GetContactList(args.CurrentUser);
                    ucContactList.SetContacts = contacts;
                    System.Threading.Thread.Sleep(15000);
                }
            }
            else
            {
                MessageBox.Show("Yikes, wrong type of args passed to the m_bwUpdateContactList_DoWork method.");
            }
        }

        #endregion

        #endregion

    }
}
